package cn.springcloud.fix.samples.service;

import cn.springcloud.fix.samples.vo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * Spring Aop中解析spel表达式，实现更灵活的功能，http://www.ciphermagic.cn/spring-aop-spel.html
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    private static Map<Integer, User> userMap = new HashMap<>();

    static {
        userMap.put(1, new User(1, "肖战", 25));
        userMap.put(2, new User(2, "王一博", 26));
        userMap.put(3, new User(3, "杨紫", 24));
    }

    /**
     * key  ->  user::1
     */
    @CachePut(value = "user:a", key = "#user.id")
    @Override
    public User save(User user) {
        userMap.put(user.getId(), user);
        log.info("进入save方法，当前存储对象：{}", user.toString());
        return user;
    }

    /**
     * 根据方法的请求参数对其结果进行缓存，和@Cacheable不同的是，它每次都会触发真实方法的调用。
     * key  ->  user::User(id=5, name=李现2, age=30)
     */
    @CachePut(value = "user:b", key = "#user")
    @Override
    public User save2(User user) {
        userMap.put(user.getId(), user);
        log.info("进入save方法，当前存储对象：{}", user.toString());
        return user;
    }

    @CachePut(value = "user:b")
    public User save3(User user, User user2) {
        userMap.put(user.getId(), user);
        log.info("进入save方法，当前存储对象：{}", user.toString());
        return user;
    }

    /**
     * 根据条件对缓存进行清空
     * allEntries：是否清空所有缓存内容，缺省为false，如果指定为true，则方法调用后将立即清空所有缓存
     * beforeInvocation：是否在方法执行前就清空，缺省为false，如果指定为true，则在方法还没有执行的时候就清空缓存。缺省情况下，如果方法执行抛出异常，则不会清空缓存。
     */
    @CacheEvict(value = "user", key = "#id", allEntries = true)
    @Override
    public void delete(int id) {
        userMap.remove(id);
        log.info("进入delete方法，删除成功");
    }

    @CacheEvict(value = "user")
    @Override
    public void delete2(int id) {
        userMap.remove(id);
        log.info("进入delete2方法，删除成功");
    }

    /**
     * Cacheable 根据方法的请求参数对其结果进行缓存
     * key：缓存的key，可以为空，如果指定要按照SPEL表达式编写，如果不指定，则按照方法的所有参数进行组合。
     * value：缓存的名称，必须指定至少一个（如 @Cacheable (value='user')或者@Cacheable(value={'user1','user2'})）
     * condition：缓存的条件，可以为空，使用SPEL编写，返回true或者false，只有为true才进行缓存。
     */
    @Cacheable(value = "user:c", key = "#id", condition = "#id lt 10")
    @Override
    public User get(Integer id) {
        log.info("进入get方法，当前获取对象：{}", userMap.get(id) == null ? null : userMap.get(id).toString());
        return userMap.get(id);
    }

    @Cacheable(value = "emp", key = "#root.args[0]", condition = "#id > 0", unless = "#result eq null")
    public Object getById(Serializable id) {
        System.out.println("getById");
        return null;
    }

    @CachePut(value = "emp", key = "#root.args[0].id", unless = "#result eq null ")
    public Object updateEmployeeById(Object entity) {
        return null;
    }

    @CacheEvict(value = "emp", key = "#root.args[0]", condition = "#result eq true")
    public boolean removeById(Serializable id) {
        return false;
    }
}
